/*********************************************************************
	\file :           os_sw_layers\bios\services\scheduler\SchM.c
	\brief:           Periodic tasks.
	\author:          Manuel Sandoval
	\version:         1.0
	\date:            Sat, 01, March 2014
*********************************************************************/


/******************************* Includes**********************************/

#include "SchM.h"
#include "Gpt.h"
#include "Fifo_queue.h"


/******************************* Defines **********************************/


/******************************* Enumerations******************************/


/******************************* Structures *******************************/


/******************************* Global Variables **********************************/

u8 gu8SchM_Counter;
Os_TaskControlBlockType Os_Task_ID_Active;
queue Os_Fifo;
boolean Os_Task_Event = false;


/******************************* Prototypes ********************************/


/******************************* Functions ********************************/



/***************************************************************************
*
*   FUNCTION NAME: SchM_Init
*
***************************************************************************/
/**
* @brief Scheduler Initialization.
*
* This function allows the application to Initialize the Scheduler.
*
* @param[in].
*
* @return .
*
* @par Notification:
* None.
*
***************************************************************************/
void SchM_Init(Os_TaskDescriptorType* Os_Config)
{
	u8 u8Iterator;
	Os_TaskControlBlockType Os_Task_temp;

	/*!< Gpt init */
	Gpt_Init(Mcal_Gpt_Config);

	/* init the fifo buffer */

	if (true == init_queue(&Os_Fifo))
	{
		for(u8Iterator = 0; u8Iterator < TASK_MAX_NUM; u8Iterator++)
		{

			Os_Task_temp.TaskId = Os_Tasks_Config[u8Iterator].TaskId;
			Os_Task_temp.TaskPriority = Os_Tasks_Config[u8Iterator].TaskPriority;
			Os_Task_temp.TaskState = SUSPENDED;

			enqueue(&Os_Fifo, &Os_Task_temp);
		}
	}
	else
	{
		/* do nothing */
  }


	Os_Task_ID_Active.TaskId = NULL;
	Os_Task_ID_Active.TaskState = SUSPENDED;
	Os_Task_ID_Active.TaskPriority = NULL;

	/* flag for New task added or finished */
	Os_Task_Event = true;

} /* SchM_Init */



/***************************************************************************
*
*   FUNCTION NAME: SchM_DeInit
*
***************************************************************************/
/**
* @brief Scheduler De-Initialization.
*
* This function allows the application to De-Initialize the Scheduler.
*
* @param[in].
*
* @return .
*
* @par Notification:
* None.
*
***************************************************************************/
void SchM_DeInit(void)
{
	/* Stop de Timer */
	Gpt_StopTimer(0);

} /* SchM_DeInit */


/***************************************************************************
*
*   FUNCTION NAME: SchM_Start
*
***************************************************************************/
/**
* @brief Scheduler start function.
*
*
* @param[in].
*
* @return .
*
* @par Notification:
* None.
*
***************************************************************************/
/** Scheduler start function */
void SchM_Start( void  )
{
	/*!< Gpt start timer */
	Gpt_StartTimer(0, 0);
} /* SchM_Start */



/***************************************************************************
*
*   FUNCTION NAME: SchM_OsTick
*
***************************************************************************/
/**
* @brief OS tick callback function.
*
* @param[in].
*
* @return .
*
* @par Notification:
* None.
*
***************************************************************************/

/** OS tick callback function - */
void SchM_OsTick(void)
{
  /*-- Update scheduler control variable --*/
	gu8SchM_Counter++;
}


/***************************************************************************
*
*   FUNCTION NAME: SchM_Background
*
***************************************************************************/
/**
* @brief Backgroud Task.
*
* @param[in].
*
* @return .
*
* @par Notification:
* None.
*
***************************************************************************/

/** Backgroud Task - */
void SchM_Background( void  )
{
	SchM_Task_Background();
}/* SchM_Background */

/***************************************************************************
*
*   FUNCTION NAME: SchM_Dispatcher
*
***************************************************************************/
/**
* @brief Dispacher Task.
*
* @param[in].
*
* @return .
*
* @par Notification:
* None.
*
***************************************************************************/
/*!< Dispatcher Prototype. */
void SchM_Dispatcher( void)
{
	u8 u8Iterator;
	u8 u8Buffer_task_count;
	u8 u8TaskPriority_temp = 0;
	boolean Os_Task_Valid = false;
	Os_TaskControlBlockType Os_Task_Buffer = {NONE, NULL, NULL};
  Os_TaskControlBlockType Os_Task_temp = {NONE, NULL, NULL};


	if (true == Os_Task_Event)
	{
	  u8Buffer_task_count =  Os_Fifo.count;
	  
		for(u8Iterator = 0; u8Iterator < u8Buffer_task_count; u8Iterator++)
		{
			if (dequeue(&Os_Fifo, &Os_Task_temp))
			{
				if (Os_Task_temp.TaskPriority >= Os_Task_Buffer.TaskPriority)
				{
  				 if(Os_Task_Buffer.TaskId != NONE)
  				 {
  				    enqueue(&Os_Fifo, &Os_Task_Buffer);
  				 } 
  				 else
  				 {
  				  /* do nothing */
  				 }
			     
			      Os_Task_Buffer = Os_Task_temp;
				}
				else
				{
					enqueue(&Os_Fifo, &Os_Task_temp);
				}
				
				Os_Task_Valid = true;
			}
			else
			{
			  /* buffer Is Empty */
			  Os_Task_Valid = false;
				/* do nothing */
	    }
		}

    if(Os_Task_Valid)
    {
       ActivateTask(Os_Task_Buffer.TaskId);
    } 
    else
    {
      /* do nothing*/
    }
		
	}
	else
	{
		/* do nothing */
  }

	if( (Os_Task_ID_Active.TaskState == READY) &&
	    ( gu8SchM_Counter & Os_Tasks_Config[Os_Task_ID_Active.TaskId].TaskMask ) == Os_Tasks_Config[Os_Task_ID_Active.TaskId].TaskOffset )
	{

		if(NULL_PTR != Os_Tasks_Config[Os_Task_ID_Active.TaskId].TaskCallbackFunction)
		{

			//Os_Task_ID_Active.TaskId = Os_Tasks_Config[u8Iterator].TaskId;
			Os_Task_ID_Active.TaskPriority = Os_Tasks_Config[Os_Task_ID_Active.TaskId].TaskPriority;
			Os_Task_ID_Active.TaskState = RUNNING;

			/*!< Executing callback */
			Os_Tasks_Config[Os_Task_ID_Active.TaskId].TaskCallbackFunction();

		}
		else
		{
			/* do nothing */
		}
	}
	else
	{
		SchM_Background();
	}


} /* SchM_Dispatcher */



/** @} *//* End of Scheduler Group */


/*********************************************************************
	File	: os_sw_layers\bios\services\scheduler\SchM.c
*********************************************************************/
